package com.fruit.controller.wap.wechat;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import com.fruit.common.CookieUtil;
import com.fruit.common.WeChatUtils;
import com.fruit.constants.RedisConstant;
import com.fruit.controller.base.BaseController;
import com.fruit.resolver.DefiniteException;
import com.fruit.service.redis.UserRedisUtil;
import com.fruit.util.CustomUtil;
import com.fruit.util.ResultInfo;
import com.fruit.util.ShortUrlUtil;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;

/**
 * 微信相关Controller
 * 
 * @author Administrator
 * @version 2018.02.02 12:40
 *
 */
@Slf4j
@Controller
@RequestMapping(value = "/wap/wechat")
public class WeChatWapController extends BaseController {
	@Value("${wechat.open.appid}")
	private String openAppid; // 开发平台appid

	@Value("${wechat.open.secret}")
	private String openAppsecret; // 开发平台secret

	@Value("${wechat.public.appid}")
	private String appid; // 公众平台

	@Value("${wechat.public.secret}")
	private String secret; // 公众平台

	@Value("${domain}")
	private String domain;

	@Value("${h5_domain}")
	private String h5Domain;

	@Value("${top_domain}")
	private String topDomain;

	@Autowired
	private UserRedisUtil userRedisService;

	/**
	 * 获取微信公众号CODE
	 * 
	 * @param type
	 *            0代表隐式授权 1 代表显式授权
	 * @param goUrl
	 *            授权后跳转路径
	 * @param request
	 *            request
	 * @param response
	 *            response
	 * @return ModelAndView
	 * @throws UnsupportedEncodingException 
	 */
	@RequestMapping(value = "/wxValidate/getWxJsApiCode", method = { RequestMethod.GET })
	public ModelAndView getWxJsApiCode(String type, String goUrl, HttpServletRequest request,
			HttpServletResponse response) throws UnsupportedEncodingException {
		log.info("获取code路径开始");

		StringBuffer url = new StringBuffer();
		StringBuffer redirectUri = new StringBuffer();
		String contextPath = request.getContextPath();
		url.append("https://open.weixin.qq.com/connect/oauth2/authorize?appid=").append(appid);
		String scope = "snsapi_base";
		if ("1".equals(type)) {
			scope = "snsapi_userinfo";
		}
		redirectUri.append("http://").append("guobener.com").append(contextPath);
		redirectUri.append("/wap/wechat/wxValidate/getWxStation?").append("pDomain=").append(domain);
		redirectUri.append("&goUrl=").append(URLEncoder.encode(goUrl, "UTF-8"));

		url.append("&redirect_uri=").append(URLEncoder.encode(redirectUri.toString(), "UTF-8"));
		url.append("&response_type=code&scope=").append(scope).append("&state=1#wechat_redirect");
		log.info("获取code路径{}", url.toString());
		return new ModelAndView(new RedirectView(url.toString()));

	}

	/**
	 * 获取微信公众号中转站
	 * 
	 * @param goUrl
	 *            goUrl
	 * @param code
	 *            code
	 * @param session
	 *            session
	 * @param request
	 *            request
	 * @param response
	 *            response
	 * @return String
	 */
	@RequestMapping(value = "/wxValidate/getWxStation", method = { RequestMethod.GET })
	public String getWxStation(String goUrl, String pDomain, String code, HttpSession session,
			HttpServletRequest request, HttpServletResponse response) {
		log.info("微信授权中转站------开始");
		if (!StringUtils.isEmpty(code)) {
			try {
				log.info("中转站-goUrl：{}", goUrl);
				StringBuffer url = new StringBuffer();
				url.append(pDomain).append("/wap/wechat/wxValidate/getWxJsApiOpenid?goUrl=").append(URLEncoder.encode(goUrl, "UTF-8"));
				url.append("&code=").append(code);
				// 到跳转处理
				log.info("中转站URL:{}", url.toString());
				return "redirect:" + url.toString();
			} catch (Exception e) {
				log.error("微信授权中转站异常{}", e);
				throw new DefiniteException("微信授权中转站异常");
			}
		} else {
			log.error("获取openid调用获取授权code为空{}", code);
			throw new DefiniteException("获取openid调用获取授权code为空");
		}
	}
	
	/**
	 * 获取微信公众号openid
	 * 
	 * @param goUrl
	 *            goUrl
	 * @param code
	 *            code
	 * @param session
	 *            session
	 * @param request
	 *            request
	 * @param response
	 *            response
	 * @return String
	 */
	@RequestMapping(value = "/wxValidate/getWxJsApiOpenid", method = { RequestMethod.GET })
	public String getWxJsApiOpenid(String goUrl, String code, HttpSession session,
			HttpServletRequest request, HttpServletResponse response) {
		log.info("获取openid服务------开始");
		if (!StringUtils.isEmpty(code)) {
			try {
				// 获取token
				log.info("goUrl地址URL:{}", goUrl);
				JSONObject openjson = WeChatUtils.getWxJsApiToken(appid, secret, code);
				if (openjson == null) {
					log.error("获取token调用异常");
					throw new DefiniteException("获取token调用异常");
				}
				log.info("获取token结果{}", openjson.toString());
				String openid = openjson.getString("openid");

				CookieUtil.setCookie(response, "publicOpenid", "" + openid, 30, "/", topDomain);
				// 到跳转处理
				return "redirect:" + goUrl;
			} catch (Exception e) {
				log.error("授权处理异常{}", e);
				throw new DefiniteException("授权处理异常");
			}
		} else {
			log.error("获取openid调用获取授权code为空{}", code);
			throw new DefiniteException("获取openid调用获取授权code为空");
		}
	}

	/**
	 * 返回微信公众号签名信息
	 * 
	 * @param url
	 *            url
	 * @param request
	 *            request
	 * @return Map<String, Object>
	 */
	@RequestMapping(value = "/wxValidate/getJsapiSigna", method = { RequestMethod.POST, RequestMethod.GET })
	@ResponseBody
	public Map<String, Object> getJsapiSigna(String url, HttpServletRequest request) {
		log.info("【微信公众号签名信息】---【开始】--url={} ", url);
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			if (StringUtils.isEmpty(url)) {
				result.put("result", this.initResult(ResultInfo.ERROR, "param_error", "url不能为空"));
				return result;
			}
			String jsapiTicket = userRedisService.getUserToken(RedisConstant.WAP_PUBLIC_TOOKEN);
			log.info("缓存中获取jsapiTicket 结果{}", jsapiTicket);
			if (StringUtils.isEmpty(jsapiTicket)) { // 缓存取不到则重新获取
				JSONObject tocken = WeChatUtils.getWxJsApiJsToken(appid, secret);
				if (tocken == null) {
					log.error("获取token调用异常");
					result.put("result", this.initResult(ResultInfo.ERROR, "token_error", "获取分享token异常"));
					return result;
				}
				log.info("获取微信公众号token结果{}", tocken.toString());
				String accessToken = tocken.getString("access_token");
				JSONObject ticket = WeChatUtils.getWxJsApiJsTicket(accessToken);
				if (ticket == null) {
					log.error("获取jsapi_ticket调用异常");
					result.put("result", this.initResult(ResultInfo.ERROR, "ticket_error", "获取jsapi_ticket调用异常"));
					return result;
				}
				log.info("获取微信公众号jsapi_ticket结果{}", ticket.toString());
				jsapiTicket = ticket.getString("ticket");
				if (StringUtils.isEmpty(jsapiTicket)) {
					log.error("获取jsapi_ticket获取异常{}", jsapiTicket);
					result.put("result", this.initResult(ResultInfo.ERROR, "ticket_error", "获取jsapi_ticket调用异常"));
					return result;
				} else {
					try {
						userRedisService.setUserToken(RedisConstant.WAP_PUBLIC_TOOKEN, jsapiTicket, 5400);
					} catch (Exception e) {
						log.info("缓存中设置jsapiTicket失败jsapiTicket={},e={}", jsapiTicket, e);
					}

				}
			}

			String nonce = ShortUrlUtil.buildCode(8);
			String timestamp = Long.toString(System.currentTimeMillis() / 1000);
			Map<String, String> params = new TreeMap<String, String>();
			params.put("noncestr", nonce); // 随机字符串
			params.put("timestamp", timestamp); // 时间戳
			params.put("url", url); // url
			params.put("jsapi_ticket", jsapiTicket); // jsapi_ticket
			// 创建签名
			String signature = CustomUtil.createPublicSign(params);
			if (signature == null) {
				log.error("获取signature加密异常{}", signature);
				result.put("result", this.initResult(ResultInfo.ERROR, "signature_error", "获取signature加密异常"));
				return result;
			}
			result.put("noncestr", nonce); // 随机字符串
			result.put("timestamp", timestamp); // 时间戳
			result.put("appId", appid); // appid
			result.put("signature", signature); // url
			result.put("result", this.initResult(ResultInfo.SUCCESS, "ok", "操作成功！"));
		} catch (Exception e) {
			log.info("【微信公众号签名信息】---【异常】---{}", e);
			result.put("result", this.initResult(ResultInfo.ERROR, "exception", "系统异常"));
		}
		log.info("返回结果：{}", result.toString());
		return result;
	}

}
